#pragma once 
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<sys/types.h>
#include<netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<pthread.h>

#define BACKLOG 5
//类定义Tcp协议服务器
class TcpServer{

    private:
    int port;//端口
    int listen_sock;//后面定义的套接字
    static TcpServer* svr;//后面静态成函数自引用指针

    //私有化构造函数，避免外界定义，不暴露端口
    TcpServer(int _port):port(_port),listen_sock(-1)
    {}
    TcpServer(const TcpServer &s)
    {}


    public:
    static TcpServer* getinstace(int port)
    {
        //初始化线程互斥锁
        static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
        if(nullptr==svr){
            pthread_mutex_lock(&lock);
            if(nullptr==svr){
                svr=new TcpServer(port);
                svr->InitServer();
            }
        }


    }

    void InitServer()
    {
        Sock();
        Bind();
        Listen();
        //创建套接字并且绑定监听成功
    }

    void Sockt()
    {
        //指定通信协议  指定数据传输格式（字节流/数据报等） 协议套接字指定的特定协议，一般指定为0
        listen_sock=socket(AF_INET,SOCK_STREAM,0);
        if(listen_sock<0)
        {
            //创建套接字失败
            exit(1);
        }
        int opt=1;
        //套接字层次：TCP层次：IP层次：设置选项的值：选项长度：
        setsockopt(listen_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
        //创建套接字成功

    }

    void Bind()
    {
        //结构体sockaddr:创建根据地址创建socket时的地址协议不同而不同
        struct sockaddr_in local;
        memset(&local,0,sizeof(local));
        //.sin_family:协议类型，AF_INET表示IPV4协议
        local.sin_family=AF_INET;
        //sin.port表示端口号，一般要主机转网络，或者网络转主机的大小端转换
        local.sin_port=htons(port);
        //.s_addr:表示IP地址
        local.sin_addr.s_addr=INADDR_ANY;//绑定任意IP,云服务器不能绑定公网IP
        //绑定：套接字标识符：结构体sockaddr：sockaddr长度
        if(bind(listen_sock,(struct sockaddr*)&local,sizeof(local))<0)
        {
            exit(2);
            //绑定套接字失败

        }
    }

    void Listen()
    {
        if(listen(listen_sock,BACKLOG)<0)
        {
            exit(3);
            //监听失败
        }
    }

    int Sock()
    {
        return listen_sock;
    }

    ~TcpServer()
    {
        if(listen_sock>=0) close(listen_sock);
    }

};

TcpServer* TcpServer::svr=nullptr;//静态成员外部初始化